{-# LANGUAGE TypeOperators              #-}
{-# OPTIONS -Wall #-}

--------------------------------------------------------------------------------
-- |
-- Module      :  Ochre.Language.GensRaw
-- Copyright   :  (c) Stephen Tetley 2013
-- License     :  BSD3
--
-- Maintainer  :  stephen.tetley@gmail.com
-- Stability   :  unstable
-- Portability :  GHC
--
-- Orchestra gentables - bindable to variables via @ftgen@.
-- 
--------------------------------------------------------------------------------

module Ochre.Language.GensRaw
  (

   

    gen01
  , gen01N

  , gen02
  , gen02N

  , gen07
  , gen09  
  , gen10

  , gen11
  , gen16

  , gen20
  , gen20N

  , gen23
  , gen23N

  , gen25
  , gen25N

  , gen27
  , gen27N

  ) where

import Ochre.Language.GensBase
import Ochre.Language.Prim


gen01 :: IString -> IFloat -> IInt -> IInt -> Gen
gen01 = gen01_ PVE

gen01N :: IString -> IFloat -> IInt -> IInt -> Gen
gen01N = gen01_ NVE

gen01_ :: Signum -> IString -> IFloat -> IInt -> IInt -> Gen
gen01_ sign filecod skip format chan = 
    makeGenP (tableSign sign 1) test err_msg vals
  where
    test    = \a -> (==0) a || isPow2Succ a
    vals    = [ getPValue filecod, getPValue skip
              , getPValue format,  getPValue chan ]   
    err_msg = "gen01 - size 0 for size=file-length or size pow 2 or pow2+1"



-- | Commonly use gen02N...
--
gen02 :: [IInt] -> Gen
gen02 = gen02_ PVE

gen02N :: [IInt] -> Gen
gen02N = gen02_ NVE

gen02_ :: Signum -> [IInt] -> Gen
gen02_ sign xs = makeGenP (tableSign sign 2) isPow2Succ err_msg vals
  where
    vals    = map getPValue xs
    err_msg = "gen01 - size 0 for size=file-length or size pow 2 or pow2+1"





--------------------------------------------------------------------------------
-- 


-- | Better to use a fence or not?
--
gen07 :: IFloat -> [IInt ::: IFloat] -> Gen
gen07 x1 xss = makeGenP 7 isPow2Succ err_msg vals
  where
    vals    = getPValue x1 : concatMap fn xss
    fn      = \(n ::: x2) -> [getPValue n, getPValue x2]
    err_msg = "gen07 - size is not a pow of 2 or pow2+1"



gen09 :: [IFloat] -> Gen
gen09 xs = makeGenP 9 isPow2Succ err_msg vals
  where
    vals    = map getPValue xs
    err_msg = "gen09 - size is not a pow of 2 or pow2+1"



gen10 :: [IFloat] -> Gen
gen10 xs = makeGenP 10 isPow2Succ err_msg vals
  where
    vals    = map getPValue xs
    err_msg = "gen10 - size is not a pow of 2 or pow2+1"




-- Design problem - GEN11 has optional args.


-- | Default value for lh is 1, default value for r is 1...
--
gen11 :: IInt -> IFloat -> IFloat -> Gen
gen11 nh lh r = makeGenP 11 isPow2Succ err_msg vals 
  where
    vals    = [getPValue nh, getPValue lh, getPValue r]
    err_msg = "gen11 - size is not a pow of 2 or pow2+1"


-- | type is 0 for straight, otherwise if it is positive 
-- it is slowly rising/decaying, if negative it is fast 
-- rising/decaying.
--
gen16 :: IFloat -> IInt -> IFloat -> IFloat -> Gen
gen16 beg dur typ end = makeGenP 16 isPow2Succ err_msg vals 
  where
    vals    = [ getPValue beg, getPValue dur
              , getPValue typ, getPValue end ]
    err_msg = "gen16 - size is not a pow of 2 or pow2+1"



-- Should we have an Enum for the window types?

gen20 :: IInt -> IInt -> Maybe IInt -> Gen
gen20 = gen20_ PVE


gen20N :: IInt -> IInt -> Maybe IInt -> Gen
gen20N = gen20_ NVE

gen20_ :: Signum -> IInt -> IInt -> Maybe IInt -> Gen
gen20_ sign win maxm opt = 
    makeGenP (tableSign sign 20) isPow2Succ err_msg vals 
  where
    vals    = case opt of
                Just win_param -> [ getPValue win, getPValue maxm
                                  , getPValue win_param ]
                Nothing        -> [ getPValue win, getPValue maxm]
    err_msg = "gen20 - size is not a pow of 2 or pow2+1"


gen23 :: IString -> Gen
gen23 = gen23_ PVE

gen23N :: IString -> Gen
gen23N = gen23_ NVE

gen23_ :: Signum -> IString -> Gen
gen23_ sign filename = 
    makeGenP (tableSign sign 23) isPow2Succ err_msg [getPValue filename]
  where
    err_msg = "gen23 - size is not a pow of 2 or pow2+1"


gen25 :: IInt -> [IFloat ::: IInt] -> Gen
gen25 = gen25_ PVE

gen25N :: IInt -> [IFloat ::: IInt] -> Gen
gen25N = gen25_ NVE

gen25_ :: Signum -> IInt -> [IFloat ::: IInt] -> Gen
gen25_ sign x1 xss = 
    makeGenP (tableSign sign 25) isPow2Succ err_msg vals
  where
    vals    = getPValue x1 : concatMap fn xss
    fn      = \(y1 ::: x2) -> [ getPValue y1 , getPValue x2 ]
    err_msg = "gen25 - size is not a pow of 2 or pow2+1"


gen27 :: IInt -> [ IInt ::: IFloat ] -> Gen
gen27 = gen27_ PVE

gen27N :: IInt -> [ IInt ::: IFloat ] -> Gen
gen27N = gen27_ NVE


gen27_ :: Signum -> IInt -> [ IInt ::: IFloat ] -> Gen
gen27_ sign x1 xss = makeGenP (tableSign sign 27) isPow2Succ err_msg vals
  where
    vals    = getPValue x1 : concatMap fn xss
    fn      = \(y1 ::: x2) -> [ getPValue y1 , getPValue x2 ]
    err_msg = "gen27 - size is not a pow of 2 or pow2+1"